function isContained(a, b) {
    if (!(a instanceof Array) || !(b instanceof Array)) return false;
    if (a.length < b.length) return false;
    for (var i = 0, len = b.length; i < len; i++) {
        if (a.indexOf(b[i]) == -1) return false;
    }
    return true;
}
/**
* 获得指定数组的所有组合
*/
function arrayCombine(targetArr = [], count = 1, bladder) {
    if (!Array.isArray(targetArr)) return []

    const resultArrs = []
    // 所有组合的 01 排列
    const flagArrs = getFlagArrs(targetArr.length, count)

    while (flagArrs.length) {
        const flagArr = flagArrs.shift()
        var data = targetArr.filter((_, idx) => flagArr[idx]);
        if (bladder.length > 0) {
            if (isContained(data, bladder)) {
                resultArrs.push(data)
            }

        } else {
            resultArrs.push(data)
        }
    }
    return resultArrs
}
/**
 * 获得从 m 中取 n 的所有组合
 * 思路如下：
 * 生成一个长度为 m 的数组，
 * 数组元素的值为 1 表示其下标代表的数被选中，为 0 则没选中。
 *
 * 1. 初始化数组，前 n 个元素置 1，表示第一个组合为前 n 个数；
 * 2. 从左到右扫描数组元素值的 “10” 组合，找到第一个 “10” 组合后将其变为 “01” 组合；
 * 3. 将其左边的所有 “1” 全部移动到数组的最左端
 * 4. 当 n 个 “1” 全部移动到最右端时（没有 “10” 组合了），得到了最后一个组合。
 */
function getFlagArrs(m, n = 1) {
    if (n < 1 || m < n) return []

    // 先生成一个长度为 m 字符串，开头为 n 个 1， 例如“11100”
    let str = '1'.repeat(n) + '0'.repeat(m - n)
    let pos
    // 1
    const resultArrs = [Array.from(str, x => Number(x))]
    const keyStr = '10'

    while (str.indexOf(keyStr) > -1) {
        pos = str.indexOf(keyStr)
        // 2
        str = str.replace(keyStr, '01')
        // 3
        str = Array.from(str.slice(0, pos))
            .sort((a, b) => b - a)
            .join('') + str.slice(pos)
        // 4
        resultArrs.push(Array.from(str, x => Number(x)))
    }
    return resultArrs
}

// 执行组合排列的函数
function redDoExchange(arr) {
    var len = arr.length;
    // 当数组大于等于2个的时候
    if (len >= 2) {
        // 第一个数组的长度
        var len1 = arr[0].length;
        // 第二个数组的长度
        var len2 = arr[1].length;
        // 2个数组产生的组合数
        var lenBoth = len1 * len2;
        //  申明一个新数组,做数据暂存
        var items = new Array(lenBoth);
        // 申明新数组的索引
        var index = 0;
        // 2层嵌套循环,将组合放到新数组中
        for (var i = 0; i < len1; i++) {
            for (var j = 0; j < len2; j++) {
                items[index] = (arr[0][i] + "," + arr[1][j]).split(',').sort();
                index++;
            }
        }
        // 将新组合的数组并到原数组中
        var newArr = new Array(len - 1);
        for (var i = 2; i < arr.length; i++) {
            newArr[i - 1] = arr[i];
        }
        newArr[0] = items;
        // 执行回调
        return doExchange(newArr);
    } else {
        return arr[0];
    }
}

// 执行组合排列的函数
function doExchange(arr) {
    var len = arr.length;
    // 当数组大于等于2个的时候
    if (len >= 2) {
        // 第一个数组的长度
        var len1 = arr[0].length;
        // 第二个数组的长度
        var len2 = arr[1].length;
        // 2个数组产生的组合数
        var lenBoth = len1 * len2;
        //  申明一个新数组,做数据暂存
        var items = new Array(lenBoth);
        // 申明新数组的索引
        var index = 0;
        // 2层嵌套循环,将组合放到新数组中
        for (var i = 0; i < len1; i++) {
            for (var j = 0; j < len2; j++) {
                items[index] = (arr[0][i].sort()) + "|" + (arr[1][j].sort());
                index++;
            }
        }
        // 将新组合的数组并到原数组中
        var newArr = new Array(len - 1);
        for (var i = 2; i < arr.length; i++) {
            newArr[i - 1] = arr[i];
        }
        newArr[0] = items;
        // 执行回调
        return doExchange(newArr);
    } else {
        return arr[0];
    }
}

/**
 * 
 * @param {*类型0单式1复式2胆拖} type 
 * @param {*期号} Number 
 * @param {*标准04,07,13,15,16,17,18|09,11胆拖22#24,29,31,32,35|02#06,10} betNumber 
 * @param {*倍数} multNum 
 */
function betNumberComb(type, Number, red_bladder, red_ball, blue_bladder, blue_ball, multNum) {
    var BetNumber = {};
    var betRecords = [];
    let bet_n = '';
    if (red_bladder.length > 0) {
        bet_n += red_bladder.join(',') + '#';
    }
    bet_n += red_ball.sort().join(',') + '|';
    if (blue_bladder.length > 0) {
        bet_n += blue_bladder.join(',') + '#';
    }
    bet_n += blue_ball.sort().join(',')
    switch (type) {
        case 0:
            BetNumber = {
                "Type": type,
                "NoID": type,
                "Number": Number,
                "BetNumber": bet_n
            }
            var betRecordObj = {
                "Type": type,
                "NoID": type,
                "buyNumber": bet_n,
                "multNum": multNum
            }
            betRecords.push(betRecordObj);
            break;
        case 1:
            BetNumber = {
                "Type": type,
                "NoID": type,
                "Number": Number,
                "BetNumber": bet_n
            }
            var balls = bet_n.split("|");
            var red_ball = arrayCombine(red_ball, 5, []);
            var blue_ball = arrayCombine(blue_ball, 2, []);
            var records = doExchange([red_ball, blue_ball]);
            for (let i = 0; i < records.length; i++) {
                betRecords.push({
                    "Type": type,
                    "NoID": type,
                    "buyNumber": records[i],
                    "multNum": multNum
                });
            }
            break;
        case 2:
            //22,22#24,29,31,32,35|02,03#06,10
            console.log(bet_n);
            BetNumber = {
                "Type": type,
                "NoID": type,
                "Number": Number,
                "BetNumber": bet_n
            }
            var red_ball_arr = red_bladder.concat(red_ball);
            red_ball_arr = arrayCombine(red_ball_arr, 5, red_bladder);
            
            var blue_ball_arr = blue_bladder.concat(blue_ball);
            blue_ball_arr = arrayCombine(blue_ball_arr, 2, blue_bladder);

            var records = doExchange([red_ball_arr, blue_ball_arr]);
            for (let i = 0; i < records.length; i++) {
                betRecords.push({
                    "Type": type,
                    "NoID": type,
                    "buyNumber": records[i],
                    "multNum": multNum
                });
            }
            break;
    }
    return {
        BetNumber: BetNumber,
        betRecords: betRecords,
        betCount: betRecords.length,
        betAmount: betRecords.length * 2,
    }
}

function getComNum($sumCount, $selectCount) {
    $sum = 1;
    $sum1 = 1;
    $sum2 = 1;
    for ($i = 1; $i <= $sumCount; $i++) {
        $sum = $sum * $i;
    }
    for ($i = 1; $i <= ($sumCount - $selectCount); $i++) {
        $sum1 = $sum1 * $i;
    }
    for ($i = 1; $i <= $selectCount; $i++) {
        $sum2 = $sum2 * $i;
    }
    return Math.ceil($sum / ($sum1 * $sum2));
}
var redDanCountTable = {
    '1': [0, 0, 0, 0, 1, 5, 15, 35, 70, 126, 210, 330, 495, 715, 1001, 1365, 1820, 2380, 3060, 3876, 4845, 5985, 7315, 8855],
    '2': [0, 0, 0, 1, 4, 10, 20, 35, 56, 84, 120, 165, 220, 286, 364, 455, 560, 680, 816, 969, 1140, 1330, 1540, 1771],
    '3': [0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253],
    '4': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
};
var blueDanCountTable = {
    '1': [0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
};
module.exports = {
    betNumberComb: betNumberComb,
    getComNum: getComNum,
    redDanCountTable: redDanCountTable,
    blueDanCountTable: blueDanCountTable
};